package xmlrpc.spring.xmlrpc.client;

import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
import org.apache.xmlrpc.client.XmlRpcLiteHttpTransportFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import java.net.MalformedURLException;
import java.net.URL;


public class XmlRpcClientWrapperImpl implements XmlRpcClientWrapper {

    private static final Logger logger = LoggerFactory.getLogger(XmlRpcClientWrapperImpl.class);
    /**
     * 远程服务的URL地址，默认http://localhost/xmlrpc
     */
    private String url = "http://localhost/xmlrpc";
    /**
     * 最多的连接尝试次数，默认3次
     */
    private int maxTry = 3;
    /**
     * 服务连接超时的时长（单位：毫秒），默认30000ms
     */
    private int connectionTimeout = 30000;
    private XmlRpcClient client;
    /**
     * 是否支持扩展，默认：true
     */
    private boolean enabledForExtensions = true;
    /**
     * 默认：false
     */
    private boolean enabledForExceptions = false;
    /**
     * 默认：false
     */
    private boolean contentLengthOptional = false;
    /**
     * 字符编码，默认：GBK
     */
    private String basicEncoding = "GBK";
    /**
     * 连接密码
     */
    private String basicPassword;
    /**
     * 连接密码用户名
     */
    private String basicUserName;

    @PostConstruct
    public void init() {
        XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
        try {
            config.setServerURL(new URL(url));
            config.setEnabledForExtensions(enabledForExtensions);
            config.setEnabledForExceptions(enabledForExceptions);
            config.setConnectionTimeout(connectionTimeout);
            config.setContentLengthOptional(contentLengthOptional);
            config.setBasicEncoding(basicEncoding);
            config.setBasicPassword(basicPassword);
            config.setBasicUserName(basicUserName);
            client = new XmlRpcClient();
            client.setConfig(config);
            client.setTransportFactory(new XmlRpcLiteHttpTransportFactory(client));
        } catch (MalformedURLException e) {
            logger.error(e.getMessage());
            throw new IllegalArgumentException("the url:" + url + " could not determine the server!");
        }
    }

    /*
     * (non-Javadoc)
     * @see com.focustech.extend.spring.xmlrpc.client.XmlRpcClientWrapper#execute(java.lang.String, java.lang.Object[])
     */
    public Object execute(String serviceName, Object[] parameters) {
        Object mOutput = null;
        try {
            boolean run = false;
            Throwable runE = null;
            for (int i = 0; i < maxTry; i++) {
                try {
                    mOutput = client.execute(serviceName, parameters);
                    run = true;
                    break;
                } catch (Throwable e) {
                    e.printStackTrace();
                    runE = e;
                }
                Thread.sleep(1000);
            }
            if (!run) {
                throw new Exception("重复请求“" + maxTry + "”次后没有成功。", runE);
            }
        } catch (Exception e) {
            String param = "";
            for (int i = 0; (null != parameters) && (i < parameters.length); i++) {
                param += parameters[i].toString();
            }
            logger.error("service:" + serviceName + " parameters:" + param + " error!", e);
            throw new IllegalArgumentException("service:" + serviceName + " error!");
        }
        return mOutput;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public boolean isEnabledForExtensions() {
        return enabledForExtensions;
    }

    public void setEnabledForExtensions(boolean enabledForExtensions) {
        this.enabledForExtensions = enabledForExtensions;
    }

    public boolean isEnabledForExceptions() {
        return enabledForExceptions;
    }

    public void setEnabledForExceptions(boolean enabledForExceptions) {
        this.enabledForExceptions = enabledForExceptions;
    }

    public int getMaxTry() {
        return maxTry;
    }

    public void setMaxTry(int maxTry) {
        this.maxTry = maxTry;
    }

    public int getConnectionTimeout() {
        return connectionTimeout;
    }

    public void setConnectionTimeout(int connectionTimeout) {
        this.connectionTimeout = connectionTimeout;
    }

    public boolean isContentLengthOptional() {
        return contentLengthOptional;
    }

    public void setContentLengthOptional(boolean contentLengthOptional) {
        this.contentLengthOptional = contentLengthOptional;
    }

    public String getBasicEncoding() {
        return basicEncoding;
    }

    public void setBasicEncoding(String basicEncoding) {
        this.basicEncoding = basicEncoding;
    }

    public String getBasicPassword() {
        return basicPassword;
    }

    public void setBasicPassword(String basicPassword) {
        this.basicPassword = basicPassword;
    }

    public String getBasicUserName() {
        return basicUserName;
    }

    public void setBasicUserName(String basicUserName) {
        this.basicUserName = basicUserName;
    }
}
